#include "stream_puller_net.h"

namespace stream {

RKStreamPullerNET::RKStreamPullerNET(StreamPullerInfo* spinfo, LogInfo* log_info):
    BasePuller(spinfo, log_info) {
  src_handle=0, dst_handle=0, resize_handle=0;
  src_buf=nullptr, dst_buf=nullptr, resize_buf=nullptr;
  cur_fps = 1;
}

RKStreamPullerNET::~RKStreamPullerNET() {

}

int RKStreamPullerNET::get_frame(stream::ImageBlob& buffer) {
  int ret = 0;
  queue_lock.lock();
  if (queue_data.empty()) { queue_lock.unlock(); return -1; }
  buffer = queue_data.front();
  queue_data.pop();
  queue_lock.unlock();
  return 0;
}

int RKStreamPullerNET::release_mpp(int ret) {
	// if (packet) {
	// 	mpp_packet_deinit(&packet);
	// 	packet = NULL;
	// }

	// if (frame) {
	// 	mpp_frame_deinit(&frame);
	// 	frame = NULL;
	// }

	if (ctx) {
		mpp_destroy(ctx);
		ctx = NULL;
	}

	if (pkt_grp) {
		mpp_buffer_group_put(pkt_grp);
		pkt_grp = NULL;
	}

	if (frm_grp) {
		mpp_buffer_group_put(frm_grp);
		frm_grp = NULL;
	}
  return ret;
}

int RKStreamPullerNET::init_mpp() {
  int ret = 0;
  // release_mpp(0);
  
  // 初始化
	ret = mpp_create(&ctx, &mpi);
	if (MPP_OK != ret) {
		printf("mpp_create failed\n");
    return release_mpp(-1);
	}

  //设置该参数之后会导致内部分帧，我们不需要，就是默认的发送一帧。
	// NOTE: decoder split mode need to be set before init
  // need_split = 1;
	// mpi_cmd = MPP_DEC_SET_PARSER_SPLIT_MODE;
	// param = &need_split;
	// ret = mpi->control(ctx, mpi_cmd, param);
	// if (MPP_OK != ret) {
	// 	printf("mpi->control failed\n");
  //   return release_mpp(-1);
	// }

  ret = mpp_init(ctx, MPP_CTX_DEC, (MppCodingType)encode_type);
	if (MPP_OK != ret) {
		printf("mpp_init failed\n");
    return release_mpp(-1);
	}

  // // NOTE: timeout value please refer to MppPollType definition
  // //  0   - non-block call (default)
  // // -1   - block call
  // // +val - timeout value in ms
  // {
  //   MppPollType timeout = MPP_POLL_BLOCK;
  //   MppParam param = &timeout;

  //   ret = mpi->control(ctx, MPP_SET_OUTPUT_TIMEOUT, param);
  //   if (ret) {
  //       mpp_err("Failed to set output timeout %d ret %d\n", timeout, ret);
  //   return -1;
  //   }
  // }

  // MppDecCfg cfg       = NULL;
  // mpp_dec_cfg_init(&cfg);
  // ret = mpi->control(ctx, MPP_DEC_GET_CFG, cfg);
  // if (ret) {
  //   mpp_err("%p failed to get decoder cfg ret %d\n", ctx, ret);
  //   return -1;
  // }
  // ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
  // if (ret) {
  //   mpp_err("%p failed to set split_parse ret %d\n", ctx, ret);
  //   return -1;
  // }

  // ret = mpi->control(ctx, MPP_DEC_SET_CFG, cfg);
  // if (ret) {
  //   mpp_err("%p failed to set cfg %p ret %d\n", ctx, cfg, ret);
  //   return -1;
  // }
  MppFrameFormat  format;
  // format = MPP_FMT_RGB888;
  format = MPP_FMT_YUV420P;
  /* NOTE: change output format before jpeg decoding */
  if (MPP_FRAME_FMT_IS_YUV(format) || MPP_FRAME_FMT_IS_RGB(format)) {
      MPP_RET ret = mpi->control(ctx, MPP_DEC_SET_OUTPUT_FORMAT, &format);
      if (ret) {
          printf("Failed to set output format 0x%x\n", format);
          return NULL;
      }
  }

  return ret;
}

int RKStreamPullerNET::release_rga(int ret){
  if (src_handle)
      releasebuffer_handle(src_handle);
  if (dst_handle)
      releasebuffer_handle(dst_handle);

  // 使用rga
  dma_buf_free(dst_buf_size, &dst_dma_fd, (void *)dst_buf);
  dma_buf_free(src_buf_size, &src_dma_fd, (void *)src_buf);
  return ret;
}
int RKStreamPullerNET::release_resize_rga(int ret){
  if (resize_handle) releasebuffer_handle(resize_handle);

  if (resize_buf) free(resize_buf);
  return ret;
}

int RKStreamPullerNET::init_rga(){
  int ret = 0;
  memset(&src_img, 0, sizeof(src_img));
  memset(&dst_img, 0, sizeof(dst_img));

  src_format = RK_FORMAT_YCbCr_420_SP;
  dst_format = RK_FORMAT_BGR_888;
  src_buf_size = puller_ifo->oriWidth * puller_ifo->oriHeight * get_bpp_from_format(src_format);
  dst_buf_size = puller_ifo->oriWidth * puller_ifo->oriHeight * get_bpp_from_format(dst_format);
  printf("copy_buffer src_buf_size:%d,dst_buf_size:%d\n",src_buf_size,dst_buf_size);

  ret = dma_buf_alloc(DMA_HEAP_DMA32_UNCACHED_PATH, src_buf_size, &src_dma_fd, (void **)&(src_buf));
  printf("alloc src dma_buf_alloc ret:%d\n", ret);
  if (ret < 0) {
    printf("alloc src dma_heap buffer failed!\n");
    return -1;
  }

  ret = dma_buf_alloc(DMA_HEAP_DMA32_UNCACHED_PATH, dst_buf_size, &dst_dma_fd, (void **)&(dst_buf));
  printf("alloc dst dma_buf_alloc ret:%d\n", ret);
  if (ret < 0) {
    printf("alloc dst dma_heap buffer failed!\n");
    dma_buf_free(src_buf_size, &src_dma_fd, (void*)src_buf);
    return -1;
  }

  src_handle = importbuffer_fd(src_dma_fd, src_buf_size);
  dst_handle = importbuffer_fd(dst_dma_fd, dst_buf_size);
  printf("src_handle:%d, dst_handle:%d\n", src_handle, dst_handle);
  if (src_handle <= 0 || dst_handle <= 0) {
    printf("importbuffer failed!\n");
    return release_rga(-1);
  }
  
  src_img = wrapbuffer_handle(src_handle, puller_ifo->oriWidth, puller_ifo->oriHeight, src_format);
  dst_img = wrapbuffer_handle(dst_handle, puller_ifo->oriWidth, puller_ifo->oriHeight, dst_format);

  imsetColorSpace(&src_img, IM_YUV_BT709_LIMIT_RANGE);
  imsetColorSpace(&dst_img, IM_RGB_FULL);

  return 0;
}

int RKStreamPullerNET::init_resize_rga(){
  int ret = 0;
  memset(&resize_img, 0, sizeof(resize_img));

  resize_format = RK_FORMAT_BGR_888;
  resize_buf_size = puller_ifo->useWidth * puller_ifo->useHeight * get_bpp_from_format(resize_format);

  resize_buf = (char *)malloc(resize_buf_size);
  memset(resize_buf, 0x80, resize_buf_size);

  resize_handle = importbuffer_virtualaddr(resize_buf, resize_buf_size);
  printf("resize_handle:%d\n", resize_handle);
  if (resize_handle <= 0) {
    printf("importbuffer failed!\n");
    return release_resize_rga(-1);
  }
  
  resize_img = wrapbuffer_handle(resize_handle, puller_ifo->useWidth, puller_ifo->useHeight, resize_format);
  return 0;
}
int RKStreamPullerNET::init_params() {
  int ret = 0;
  char errbuf[64];

  
  av_dict_set(&optionsDict, "stimeout", "3000000", 0);           // if don't setting this property，av_read_frame will run as block mode (ms)
  av_dict_set(&optionsDict, "bufsize", "1024000", 0);            // buffer size
  av_dict_set(&optionsDict, "rtsp_transport", puller_ifo->transferType.c_str(), 0); // transfer type,udp will faster but may lost some packet,tcp slower but stable
  if ((ret = avformat_open_input(&ifmt_ctx, puller_ifo->streamAddress.c_str(), 0, &optionsDict)) < 0) { // Open the input file for reading.
    spdlog::get("logger")->info("Could not open input file '{}' (error '{}')\n", puller_ifo->streamAddress, av_make_error_string(errbuf, sizeof(errbuf), ret));
    return -103;
  }
  spdlog::get("logger")->info("avformat_open_input ok!\n");

  if ((ret = avformat_find_stream_info(ifmt_ctx, nullptr)) < 0) { // Get information on the input file (number of streams etc.).
    spdlog::get("logger")->info("Could not open find stream info (error '%s')\n", av_make_error_string(errbuf, sizeof(errbuf), ret));
    return -102;
  } 
  spdlog::get("logger")->info("avformat_find_stream_info ok!\n");

  // // dump information
  // for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++) { av_dump_format(ifmt_ctx, i, puller_ifo->streamAddress.c_str(), 0); }
  // printf("av_dump_format ok!\n");

  // find video stream index
  for (unsigned int i = 0; i < ifmt_ctx->nb_streams; i++) { 
    AVStream *st = ifmt_ctx->streams[i];
    if (st->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audio_st_index = i; }
    else if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) { video_st_index = i; }
  }

  if (-1 == video_st_index) {
    printf("No H.264 video stream in the input file\n");
    return -100;
  }

  // getting stream msg
  bool nRestart = false;
  if (!nRestart) { 
    pVst = ifmt_ctx->streams[video_st_index];
    cur_fps = (double)pVst->r_frame_rate.num / (double)pVst->r_frame_rate.den;

    pVideoCodecCtx = pVst->codec;
    if (pVideoCodecCtx->codec_id == AV_CODEC_ID_H264) { encode_type = MPP_VIDEO_CodingAVC;}
    else if (pVideoCodecCtx->codec_id == AV_CODEC_ID_H265) { encode_type  = MPP_VIDEO_CodingHEVC;}

    // 无需ffmpeg解码
    // pVideoCodec = avcodec_find_decoder(pVideoCodecCtx->codec_id);
    // if (pVideoCodec == nullptr) {return;}
    // if (avcodec_open2(pVideoCodecCtx, pVideoCodec, nullptr) < 0) {return;}
  }
  if (encode_type == MPP_VIDEO_CodingUnused) {
    printf("[ERROR] sp_encoder error\n");
    return -101;
  }
  /*Begin decoder and display*/
  // getting stream height and width
  puller_ifo->oriWidth = pVideoCodecCtx->width;
  puller_ifo->oriHeight = pVideoCodecCtx->height;
  spdlog::get("logger")->info("decodeChn:{},oriWidth:{},oriHeight:{}, cur_fps:{}\n", puller_ifo->vdecChn, puller_ifo->oriWidth, puller_ifo->oriHeight, cur_fps);
  if (puller_ifo->oriWidth <= 0 || puller_ifo->oriHeight <= 0) {return -1;}

  // 对超过1920的图片进行resize, 节约内存
  // if (pull_mode == stream::STRATEGY_FIXTIME) {
  if (puller_ifo->oriWidth > 1920 || puller_ifo->oriHeight > 1080) {
    float ratio = std::max(puller_ifo->oriWidth*1.0 / 1920, puller_ifo->oriHeight*1.0 / 1080);
    puller_ifo->useWidth = puller_ifo->oriWidth / ratio;
    puller_ifo->useHeight = puller_ifo->oriHeight / ratio;
    puller_ifo->useHeight = puller_ifo->useHeight / 16 * 16;
    puller_ifo->useHeight = puller_ifo->useHeight / 16 * 16;
  } else {
    puller_ifo->useWidth = puller_ifo->oriWidth;
    puller_ifo->useHeight = puller_ifo->oriHeight;
  }
  spdlog::get("logger")->info("decodeChn:{},useWidth:{},useHeight:{}\n", puller_ifo->vdecChn, puller_ifo->useWidth, puller_ifo->useHeight);
  // }

  ret = init_mpp();
  if (ret != 0) {return ret;}

  // 使用rga
  ret = init_rga();
  if (ret != 0) {return ret;}
  if (puller_ifo->oriWidth != puller_ifo->useWidth || puller_ifo->oriHeight != puller_ifo->useHeight) {
    ret = init_resize_rga();
    if (ret != 0) {return ret;}
  }

  stop_flag = common::CameraOpened;
  return 0;
}


int RKStreamPullerNET::start_pull() {
  int ret = 0;

  RK_U32 pkt_done = 0;
	RK_U32 pkt_eos = 0;
	RK_U32 err_info = 0;
	RK_U32 nPutErrNum = 0;;
	// use av_packet->data initialize mpp packet

  AVPacket pkt;
  av_init_packet(&pkt);    // initialize packet.
  pkt.data = nullptr;
  pkt.size = 0;
  int av_error=0;

  int size_y = puller_ifo->oriWidth * puller_ifo->oriHeight;
  int size_uv = size_y / 2;
  std::vector<char> out_buf(size_y+size_uv);

  int frame_cnt = 0;
  // int64_t timepoint = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();;
  int idx = 0;
  float vdec_fps = 0;
  int vdec_cnt = 0;
  int64_t start_time = 0, end_time = 0, cur_time = 0, decode_time = 0;
  MppFrame frame = NULL;
  RK_U32 frm_eos = 0;
  MppPacket packet = NULL;
  int break_flag = 0;
  tmp_cnt = 0;
  stream::ImageBlob buffer(stream::ImageBlobMode_BGR);
  stop_flag = common::CameraGrabing;
  while (stop_flag == common::CameraGrabing) {
    std::this_thread::sleep_for(std::chrono::milliseconds(3));
    int try_times = 3;
    cur_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();

    ret = av_read_frame(ifmt_ctx, &pkt); // read frames
    if (ret < 0) {
      av_error++; 
      if (av_error%50==0) {spdlog::get("logger")->info("ERROR av_read_frame ret < 0, av_error:{}\n", av_error); }
      // 退出重新拉流
      if (av_error > 1000) {
        break_flag = 1; 
        spdlog::get("logger")->info("ERROR. {} av_read_frame av_error:{}\n", puller_ifo->vdecChn, av_error);
      }
      goto free;
    } else {
      // if (av_error > 0) { av_error--; }
    }
    // if (pkt.stream_index != video_st_index) { printf("stream_index != video_st_index:%d != %d\n", pkt.stream_index, video_st_index); goto free; }
    // if (pkt.flags == AV_PKT_FLAG_KEY) {printf("pkt.flags == AV_PKT_FLAG_KEY\n");}

    // 执行策略 解码关键帧
    if (pull_mode == STRATEGY_FIXTIME && cur_time - decode_time < pull_mode_value*1e3 && pkt.flags != AV_PKT_FLAG_KEY) { goto free; }


    ret = mpp_packet_init(&packet, (void*)pkt.data, pkt.size);
    mpp_packet_set_pts(packet, pkt.pts);
    try_times = 10;
    while ((ret = mpi->decode_put_packet(ctx, packet)) != 0 && try_times-- > 0) {
      spdlog::get("logger")->info("ERROR. decode_put_packet ret:{}, try_times:{}\n", ret, try_times);
      printf("decode_put_packet ret:%d\n", ret);
      std::this_thread::sleep_for(std::chrono::milliseconds(2));
    }

try_again:
    ret = mpi->decode_get_frame(ctx, &frame);
    // std::cout << "decode_get_frame ret: " << ret << " vdec_cnt:" << vdec_cnt << std::endl;
    try_times = 3;
    if (MPP_ERR_TIMEOUT == ret && try_times-- > 0) {
      std::this_thread::sleep_for(std::chrono::milliseconds(2));
      spdlog::get("logger")->info("ERROR. MPP_ERR_TIMEOUT\n", ret);
      goto try_again;
    }
    if (ret != MPP_OK) { spdlog::get("logger")->info("ERROR. decode_get_frame failed:{}\n", ret); goto free; }
    if (frame == nullptr) {goto free; }

    if (mpp_frame_get_info_change(frame)) {
      RK_U32 width = mpp_frame_get_width(frame);
      RK_U32 height = mpp_frame_get_height(frame);
      RK_U32 hor_stride = mpp_frame_get_hor_stride(frame);
      RK_U32 ver_stride = mpp_frame_get_ver_stride(frame);
      RK_U32 buf_size = mpp_frame_get_buf_size(frame);

      spdlog::get("logger")->info("decode_get_frame get info changed found\n");
      spdlog::get("logger")->info("decoder require buffer w:h [{}:{}] stride [{}:{}] buf_size {}\n", width, height, hor_stride, ver_stride, buf_size);
      ret = mpp_buffer_group_get_internal(&frm_grp, MPP_BUFFER_TYPE_ION);
      if (ret) {
        spdlog::get("logger")->info("ERROR. get mpp buffer group failed ret {}\n", ret);
        break;
      }
      mpi->control(ctx, MPP_DEC_SET_EXT_BUF_GROUP, frm_grp);
      mpi->control(ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL);
      goto free;
    } else {
      err_info = mpp_frame_get_errinfo(frame) | mpp_frame_get_discard(frame);
      if (err_info) {
        // spdlog::get("logger")->info("ERROR. decoder_get_frame get err info:{} discard:{}.\n\n", mpp_frame_get_errinfo(frame), mpp_frame_get_discard(frame)); 
        goto free;
      }
      ret = copy_buffer(frame,buffer.img,out_buf);
      if(ret != 0){
        spdlog::get("logger")->info("ERROR. copy_buffer failed ret:{}\n", ret);
        goto free;
      }
    }

    if (buffer.img.empty()) {goto free;}
    queue_lock.lock();
    if (queue_data.size() >= buffer_cnt) { queue_data.pop(); }
    queue_data.push(buffer);
    queue_lock.unlock();
    decode_time = cur_time;
    vdec_cnt++;

    if (frm_grp) {
      size_t usage = mpp_buffer_group_usage(frm_grp);
    }
free:
    // frm_eos = mpp_frame_get_eos(frame);
    if (packet) {mpp_packet_deinit(&packet);packet=nullptr;}
    if (frame) {mpp_frame_deinit(&frame);frame=nullptr;}
    if (pkt.data) {av_packet_unref(&pkt);}
    if (break_flag) {spdlog::get("logger")->info("ERROR. break.\n");break;}

    // 输出fps
    end_time = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
    if (end_time - start_time > 5 * 1e3) {
      vdec_fps = 1.0 / ((end_time - start_time) / (vdec_cnt * 1e3));
      printf("vdec_fps c:%d : %f, vdec_cnt:%d\n", puller_ifo->vdecChn, vdec_fps, vdec_cnt);
      spdlog::get("logger")->info("RKStreamPullerNET::start_pull. vdec_fps c:{} : {}, vdec_cnt:{}", puller_ifo->channelId, vdec_fps, vdec_cnt);
      vdec_cnt = 0;
      start_time = end_time;
    }
  }

  spdlog::get("logger")->info("ERROR. release_ffmpeg\n");
  release_ffmpeg();
  // free
  while (!queue_data.empty()) { queue_data.pop(); }

  stop_flag = common::CameraClosed;
  return 0;

}


int RKStreamPullerNET::copy_buffer(MppFrame &frame,cv::Mat& rgbImg,std::vector<char>& out_buf){
  RK_U32 width = 0;
  RK_U32 height = 0;
  RK_U32 h_stride = 0;
  RK_U32 v_stride = 0;
  MppBuffer buffer = NULL;
  RK_U8 *base = NULL;
  int ret = 0;


  width = mpp_frame_get_width(frame);
  height = mpp_frame_get_height(frame);
  h_stride = mpp_frame_get_hor_stride(frame);
  v_stride = mpp_frame_get_ver_stride(frame);
  buffer = mpp_frame_get_buffer(frame);

  if(width <= 0 || height <= 0 || NULL == buffer){printf("copy_buffer error return width:%d,height:%d\n",width,height);return -1;}
  base = (RK_U8 *)mpp_buffer_get_ptr(buffer);
  RK_U32 buf_size = mpp_frame_get_buf_size(frame);
  size_t base_length = mpp_buffer_get_size(buffer);
  if(base_length <= 0 || buf_size <= 0 || NULL == base){printf("copy_buffer  error return base_length:%d\n",base_length);return -1;}
  // printf("buf_size: %d  , base_length:%d\n",buf_size,base_length); // 4177920
  // printf("h_stride: %d  , v_stride:%d\n",h_stride,v_stride); // 1920 / 1088
  //存储yuv420sp

  RK_U32 i;
  RK_U8 *base_y = base;
  RK_U8 *base_c = base + h_stride * v_stride;
  int idx = 0;
  for (i = 0; i < height; i++, base_y += h_stride) {
    memcpy(out_buf.data() + idx, base_y, width);
    idx += width;
  }
  for (i = 0; i < height / 2; i++, base_c += h_stride) {
    memcpy(out_buf.data() + idx, base_c, width);
    idx += width;
  }
  // printf("out_buf size:%d\n",out_buf.size());
  int64_t time1 = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();;

  // 使用rga
  memcpy((void*)src_buf, (void*)out_buf.data(), out_buf.size());
  // memset(dst_buf, 0x80, dst_buf_size);

  ret = imcheck(src_img, dst_img, {}, {});
  if (IM_STATUS_NOERROR != ret) {
    printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
    return release_rga(-1);
  }

  ret = imcvtcolor(src_img, dst_img, src_format, dst_format);
  if (ret != IM_STATUS_SUCCESS) {
    printf("running failed, %s\n", imStrError((IM_STATUS)ret));
    return release_rga(-1);
  }

  if (puller_ifo->oriWidth != puller_ifo->useWidth || puller_ifo->oriHeight != puller_ifo->useHeight) {
    ret = imcheck(dst_img, resize_img, {}, {});
    if (IM_STATUS_NOERROR != ret) {
      printf("%d, check error! %s", __LINE__, imStrError((IM_STATUS)ret));
      return -1;
    }

    ret = imresize(dst_img, resize_img);
    if (ret != IM_STATUS_SUCCESS) {
      printf("running failed, %s\n", imStrError((IM_STATUS)ret));
      return release_resize_rga(-1);
    }
    rgbImg = cv::Mat(puller_ifo->useHeight,puller_ifo->useWidth,CV_8UC3,resize_buf);
  } else {
    rgbImg = cv::Mat(puller_ifo->oriHeight,puller_ifo->oriWidth,CV_8UC3,dst_buf);
  }



  // 使用opencv
  // cv::Mat resize_img, yuvImg = cv::Mat(height*3/2,width,CV_8UC1,out_buf.data());
	// cv::cvtColor(yuvImg, resize_img, CV_YUV2BGR_NV12);
  // if (puller_ifo->oriWidth != useWidth || puller_ifo->oriHeight != useHeight) {
  //   cv::resize(resize_img, rgbImg, cv::Size(useWidth, useHeight));
  // } else {
  //   rgbImg = resize_img;
  // }
  int64_t time2 = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();;

  total_yuv2rgb_time += time2 - time1;
  total_yuv2rgb_cnt +=1;
  if (total_yuv2rgb_cnt % 100 == 0) {
    std::cout << "yuv to rgb time: "<< total_yuv2rgb_time / total_yuv2rgb_cnt << std::endl;
    total_yuv2rgb_time = 0;
    total_yuv2rgb_cnt = 0;
    // std::string temp_path = std::to_string(tmp_cnt)+".png";
    // imwrite(temp_path, rgbImg);
  }
    return 0;
  }


void RKStreamPullerNET::release_ffmpeg() {
  avcodec_close(pVideoCodecCtx);
  avformat_close_input(&ifmt_ctx);
  // if (pFrame != nullptr) av_free(pFrame);
  ifmt_ctx = nullptr;

  delete optionsDict;
  optionsDict = nullptr;
}

int RKStreamPullerNET::stop_pull() {
  // if (stop_flag1 == common::CameraGrabing) {
  //   stop_flag1 = common::CameraClosed;
  //   while (stop_flag1 != common::CameraOpened) {
  //     spdlog::get("logger")->info("StreamPullerBase::stop_pull stop_flag1: {} ", stop_flag1);
  //     std::this_thread::sleep_for(milliseconds(50));
  //   }
  // }
  int try_cnt = 200;
  if (stop_flag == common::CameraGrabing) {
    stop_flag = common::CameraOpened;
    while (stop_flag != common::CameraClosed && try_cnt-- > 0) {
      spdlog::get("logger")->info("RKStreamPullerNET::stop_pull stop_flag: {} ", stop_flag);
      std::this_thread::sleep_for(milliseconds(50));
    }
    if (try_cnt < 0) {exit(0);}
  }
  
  // release_mpp(0);   // 此操作会导致崩溃

  // 使用rga
  release_rga(0);
  release_resize_rga(0);
  return 0;
}

}